package lib.persistence;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import jxl.*;
import jxl.read.biff.BiffException;
import javax.swing.*;

import models.Deliverable;
import models.Event;
import models.Milestone;
import models.ModelAbstract;
import models.Person;
import models.Project;
import models.Publication;

import controllers.PersonController;

//Class that handles the parsing of an excel file for project

//Currently in prototyping phase,

public class ExcelToProject 
{
	
	// named constants for cell array sizes;
	
	private static final int PERSONCELLNUM = 11;
	private static final int PUBCELLNUM = 8;
	private static final int EVENTCELLNUM = 10;
	private static final int MILECELLNUM = 12;
	private static final int PROJCELLNUM = 18;
	private static final int DELIVCELLNUM = 11;
	private static final int MAXNUMINCOLLECTIONS = 10;


	// NAMED CONSTANTS TO MAKE ACCESSING THE APPROPRIATE INDICES MORE CLEAR

	private static final int PIDINDEX = 0;
	private static final int PFIRSTINDEX = 1;
	private static final int PLASTINDEX = 2;
	private static final int EIDINDEX = 3;
	private static final int PHONEINDEX = 4;
	private static final int PTITLEINDEX = 5;
	private static final int SEXINDEX = 6;
	private static final int PDESCR = 7;


	
	
	public ExcelToProject(String file_path)
	{


		try 
		{
			Workbook workbook = Workbook.getWorkbook(new File(file_path));
			Sheet sheet = workbook.getSheet("Person");
			HashMap<Integer, Person> people = readPeople(sheet);
			sheet = workbook.getSheet("Publication");
			ArrayList<Publication> publications = readPublication (sheet, people);
			sheet = workbook.getSheet("Event");
			ArrayList<Event> events = readEvent(sheet, people);
			sheet = workbook.getSheet("Milestone");
			ArrayList<Milestone> milestones = readMilestone(sheet, people);
			sheet = workbook.getSheet("Deliverable");
			ArrayList<Deliverable> deliverables = readDeliverable(sheet, people);
			
			sheet = workbook.getSheet("Project");
			// this one is for all the marbles;
			
		} 
		catch (BiffException e) 
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
		catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
	
	// Reads people from 
	
	public static HashMap<Integer, Person> readPeople(Sheet sheet)
	{


		HashMap<Integer, Person> table = new HashMap<Integer, Person>(10);
		Cell[] cells = new Cell[PERSONCELLNUM];
		cells = getContents(sheet, cells, cells.length, 0);

		for (int row_counter = 0 ; !isEmpty(cells[0]) ; )
		{

			Person person = new Person();
			person.setId(cells[PIDINDEX].getContents());
			person.setFirstName(cells[PFIRSTINDEX].getContents());
			person.setLastName(cells[PLASTINDEX].getContents());
			person.setTitle(cells[PTITLEINDEX].getContents());
			person.setSex(cells[SEXINDEX].getContents());
			person.setEmployeeNumber(cells[EIDINDEX].getContents());
			person.setDescription(cells[PDESCR].getContents());

			table.put(person.getId(), person);	
			cells = getContents(sheet, cells, cells.length, ++row_counter);

		}

		return table;

	}

	
	private static int DELIVIDINDEX = 0;
	private static int DELIVTITLEINDEX = 1;
	private static int DELIVNUMBERINDEX = 2; 
	private static int DELIVEMPLOYEESINDEX = 3;
	private static int DELIVSTATUSINDEX = 4;
	private static int DELIVDESCRINDEX =5;
	
	private ArrayList<Deliverable> readDeliverable(Sheet sheet, HashMap<Integer, Person> table)
	{
		ArrayList<Deliverable> list = new ArrayList<Deliverable>(10);
		Cell[] cells = new Cell[DELIVCELLNUM];
		int row_counter = 0;
		cells = getContents(sheet, cells, cells.length, row_counter);
		
		
		
		while (!isEmpty(cells[0]))
		{
			Deliverable deliv = new Deliverable();
//			deliv.setActors(getPeople(cells[DELIVEMPLOYEESINDEX].getContents(), table));
			// TODO enter other fields
			
			
			cells = getContents(sheet, cells, cells.length, ++row_counter);

		}
		
		return list;
	}

	private ArrayList<Milestone> readMilestone(Sheet sheet, HashMap<Integer, Person> table) {
		
		ArrayList<Milestone> list = new ArrayList<Milestone>(10);
		Cell[] cells = new Cell[MILECELLNUM];
		int row_counter = 0;
		cells = getContents(sheet, cells, cells.length, row_counter);
		
		
		
		while (!isEmpty(cells[0]))
		{
			Milestone mile = new Milestone();
			// USE ALL SETTERS TO CREATE MILESTONE OBJECTS
			
			list.add(mile);
			
			cells = getContents(sheet, cells, cells.length, ++row_counter);

		}
		
		return list;
		
	}

	private ArrayList<Event> readEvent(Sheet sheet, HashMap<Integer, Person> table) {
		ArrayList<Event> list = new ArrayList<Event>(10);
		Cell[] cells = new Cell[EVENTCELLNUM];
		int row_counter = 0;
		cells = getContents(sheet, cells, cells.length, row_counter);
		
		
		
		while (!isEmpty(cells[0]))
		{
			Event event = new Event();
			//TODO add setters for all event fields
			
			list.add(event);
			
			cells = getContents(sheet, cells, cells.length, ++row_counter);

		}
		
		return list;
	}
	
	// Index constants because I have bad memory
	private static int PUBIDINDEX = 0;
	private static int PUBTITLEINDEX = 1;
	private static int PUBLOCATIONINDEX = 2;
	private static int PUBDATEINDEX = 3;
	private static int PUBAUTHORSINDEX = 4;
	private static int PUBDESCR = 5;

	// Returns an arraylist of publications based on a sheet. Needs hashmap to know what people to associate with it
	
	private ArrayList<Publication> readPublication(Sheet sheet, HashMap<Integer, Person> table) {
		
		ArrayList<Publication> list = new ArrayList<Publication>(10);
		Cell[] cells = new Cell[PUBCELLNUM];
		int row_counter = 0;
		cells = getContents(sheet, cells, cells.length, row_counter);
		
		
		
		while (!isEmpty(cells[0]))
		{
			Publication pub = new Publication();
			pub.setAuthors(getPeople(cells[PUBAUTHORSINDEX].getContents(), table));
			pub.setDescription(cells[PUBDESCR].getContents());
			pub.setLocation(cells[PUBLOCATIONINDEX].getContents());
			pub.setPublicationDate(stringToDate(cells[PUBDATEINDEX].getContents()));
			pub.setPublicationID(Integer.parseInt(cells[PUBIDINDEX].getContents()));
			pub.setTitle(cells[PUBTITLEINDEX].getContents());
			
			list.add(pub);
			
			cells = getContents(sheet, cells, cells.length, ++row_counter);

		}
		
		return list;
	}
	
	// Helper method, is supposed to return a list of all the people in the particular object
	// by passing it a comma delimited string of ids.

	private ArrayList<Person> getPeople(String contents,
			HashMap<Integer, Person> table) {
		
		// remove unecessary white spaces
		contents = contents.trim();
		contents = contents.replaceAll(" ", "");
		StringTokenizer tokenizer = new StringTokenizer(contents, ",");
		
		ArrayList<Person> people = new ArrayList<Person>(MAXNUMINCOLLECTIONS);
		
		while (tokenizer.hasMoreTokens())
		{
			Integer tok = Integer.parseInt(tokenizer.nextToken());
			people.add(table.get(tok));
		}
		
		return people;
		
	}


	//Validates if cell is empty

	public static boolean isEmpty(Cell cell)
	{
		if (cell.getContents().compareTo("") == 0)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
	
	// Takes care of return a cell array for a particular sheet.

	public static Cell[] getContents(Sheet sheet, Cell[] cells, int length, int row_counter)
	{			

		for(int i = 0; i < length; i++)
		{
			try
			{
				cells[i] = sheet.getCell(i, row_counter);
			}
			catch(Exception e)
			{
				e.printStackTrace();
			}
		}

		return cells;
	}

	private static <T> HashMap<Integer, T> listToHash (List<T> list)
	{
		HashMap<Integer, T> map = new HashMap<Integer, T>(MAXNUMINCOLLECTIONS);
		
		Iterator<T> iterator = list.iterator();
		while (iterator.hasNext())
		{
			T t = iterator.next();
			//map.put( new Integer (t.getId()), t);
		}
		
		return null;
	}
	
	private static Date stringToDate(String contents)
	{
			
			// todo: pare date from string; 2010-01-01 99:99:99 is the format. forget the time for now
			StringTokenizer tokenizer = new StringTokenizer(contents);
			String date = tokenizer.nextToken();
			String time = tokenizer.nextToken();
			
			// tokenize the date
			tokenizer = new StringTokenizer(date, "-");
			int year = Integer.parseInt(tokenizer.nextToken());
			int month = Integer.parseInt(tokenizer.nextToken());
			int day = Integer.parseInt(tokenizer.nextToken());
			
			// tokenize the time
			tokenizer = new StringTokenizer(time, ":");
			int hours = Integer.parseInt(tokenizer.nextToken());
			int minutes = Integer.parseInt(tokenizer.nextToken());
			int seconds = Integer.parseInt(tokenizer.nextToken());
			
			return new Date(year, month, day, hours, minutes, seconds);
			
	}

}
